﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace UniSender
{
    using Expando = Dictionary<string, object>;

    partial class Client
    {
        /// <summary>
        /// Создать e-mail для массовой рассылки
        /// </summary>
        /// <param name="message">Параметры сообщения</param>
        /// <returns>Идентификатор сообщения</returns>
        public virtual int? CreateEmailMessage(EmailMessage message)
        {
            return Apply<Native.MessageResult>("createEmailMessage", message.Serialize())
                .IfNotNull(result => result.message_id);
        }

        /// <summary>
        /// Создать SMS для массовой рассылки
        /// </summary>
        /// <param name="message">Параметры сообщения</param>
        /// <returns>Идентификатор сообщения</returns>
        public virtual int? CreateSmsMessage(SmsMessage message)
        {
            return Apply<Native.MessageResult>("createSmsMessage", message.Serialize())
                .IfNotNull(result => result.message_id);
        }

        /// <summary>
        /// Удалить сообщение
        /// </summary>
        /// <param name="messageId">Код сообщения</param>
        public virtual void DeleteMessage(int messageId)
        {
            Apply("deleteMessage", new Expando()
                {
                    { "message_id", messageId }
                });
        }

        /// <summary>
        /// Запланировать массовую отправку e-mail или SMS сообщения
        /// </summary>
        /// <param name="ags">Параметры рассылки</param>
        /// <returns>Созданная рассылка </returns>
        public virtual Campaign CreateCampaign(CampaignConfig args)
        {
            return Apply<Native.Campaign>("createCampaign", args.Serialize())
                .IfNotNull(result => new Campaign(result));
        }

        /// <summary>
        /// Получить список рассылок
        /// </summary>
        /// <param name="from">Дата и время старта рассылки, начиная с которой нужно выводить рассылки</param>
        /// <param name="to">Дата и время старта рассылки, заканчивая которой нужно выводить рассылки</param>
        /// <returns>Список рассылок</returns>
        public virtual CampaignInfo[] GetCampaigns(DateTime from, DateTime to)
        {
            return Apply<Native.CampaignInfo[]>("getCampaigns", new Expando()
                {
                    { "from", from.Stringify() },
                    { "to", to.Stringify() }
                })
                .IfNotNull(result => result.Select(r => new CampaignInfo(r)).ToArray());
        }

        /// <summary>
        /// Получить статус рассылки
        /// </summary>
        /// <param name="campaignId">Код рассылки</param>
        /// <returns>Информация о рассылке</returns>
        public virtual CampaignInfo GetCampaignStatus(int campaignId)
        {
            return Apply<Native.CampaignInfo>("getCampaignStatus", new Expando()
                {
                    { "campaign_id", campaignId }
                })
                .IfNotNull(result => new CampaignInfo(result));
        }

        /// <summary>
        /// Отправить SMS-сообщение на один номер
        /// </summary>
        /// <param name="phone">Номер получателя</param>
        /// <param name="sender">Номер или имя отправителя</param>
        /// <param name="text">Текст сообщения</param>
        /// <returns>Состояние сообщения</returns>
        public virtual SmsResult SendSms(string phone, string sender, string text)
        {
            return Apply<Native.SmsResult>("sendSms", new Expando()
                {
                    { "phone", phone },
                    { "sender", sender },
                    { "text", text }
                })
                .IfNotNull(result => new SmsResult(result));
        }

        /// <summary>
        /// Отправить SMS-сообщение на несколько номеров
        /// </summary>
        /// <param name="phones">Номера получателей</param>
        /// <param name="sender">Номер или имя отправителя</param>
        /// <param name="text">Текст сообщения</param>
        /// <returns>Состояния сообщений</returns>
        public virtual SmsResult[] SendSms(string[] phones, string sender, string text)
        {
            return Apply<Native.SmsResult[]>("sendSms", new Expando()
                {
                    { "phone", string.Join(",", phones) },
                    { "sender", sender },
                    { "text", text }
                })
                .IfNotNull(result => result.Select(r => new SmsResult(r)).ToArray());
        }

        /// <summary>
        /// Проверить статус доставки SMS
        /// </summary>
        /// <param name="id">Код сообщения</param>
        /// <returns>Информация о сообщении</returns>
        public virtual SmsState CheckSms(string id)
        {
            return Apply<Native.SmsState>("checkSms", new Expando() {
                    { "sms_id", id }
                })
                .IfNotNull(result => new SmsState(result));
        }

        /// <summary>
        /// Упрощённая отправка индивидуальных email-сообщений
        /// </summary>
        /// <param name="args">Параметры e-mail</param>
        /// <returns>Результат отправки e-mail</returns>
        public virtual EmailResult[] SendEmail(EmailConfig args)
        {
            return Apply<Native.EmailResult[]>("sendEmail", args.Serialize())
                .IfNotNull(result => result.Select(r => new EmailResult(r)).ToArray());
        }

        /// <summary>
        /// Проверить статус доставки email
        /// </summary>
        /// <param name="emailId">Код сообщения</param>
        /// <returns>Информация о сообщении</returns>
        public virtual EmailState[] CheckEmail(string emailId)
        {
            return Apply<Native.EmailStateCollection>("checkEmail", new Expando()
                {
                    { "email_id", emailId }
                })
                .IfNotNull(result => result.statuses.Select(s => new EmailState(s)).ToArray());
        }

        /// <summary>
        /// Изменить текст письма со ссылкой подтверждения подписки
        /// </summary>
        /// <param name="sender">Имя отправителя</param>
        /// <param name="senderEmail">E-mail адрес отправителя</param>
        /// <param name="subject">Строка с темой письма</param>
        /// <param name="body">Текст письма в формате HTML</param>
        /// <param name="listId">Код списка, при подписке на который будет отправлено данное письмо</param>
        public virtual void UpdateOptInEmail(string sender, string senderEmail, string subject, string body, long listId)
        {
            Apply("updateOptInEmail", new Expando()
                {
                    { "sender_name", sender },
                    { "sender_email", senderEmail },
                    { "subject", subject },
                    { "body", body },
                    { "list_id", listId }
                });
        }
    }
}
